package unicorns;

import java.util.ArrayList;

import operatingSystems.*;

public class Baby extends Thread {

	int lifeTime;
	String name;
	Mother mother;
	Semaphore checkPots;
	Semaphore wakeUpMother;
	Barrier willPlay;
	Barrier eating;
	ArrayList<Pot> pots;
	
	/**
	 * 
	 * 
	 * @param ourPlayGround the playground which the baby will play in  
	 * @param name the name of this baby
	 */

	public Baby(PlayGround ourPlayGround, int name) {

		this.checkPots = ourPlayGround.checkPots;
		this.wakeUpMother = ourPlayGround.wakeUpMother;
		this.eating = ourPlayGround.eating;
		this.willPlay = ourPlayGround.willPlay;
		this.pots = ourPlayGround.pots;
		this.lifeTime = ourPlayGround.lifeTime;
		this.mother = ourPlayGround.mother;
		this.name = "Baby " + name;

	}

	public void run() {

		for (int i = 0; i < lifeTime; i++) {

			try {
				play();
				eat();

			} catch (InterruptedException e) {

				e.printStackTrace();
			}

		}
		
		System.out.println(this.name + " is now starting his life");

	}
	
	/**
	 * This method makes the baby play for some time.
	 * Handling the face that they must play in 3s by a barrier 
	 * 
	 * @throws InterruptedException
	 */

	public void play() throws InterruptedException {

		willPlay.block();
		System.out.println(this.name + " is now playing.");
		this.sleep(200);

	}
	
	/**
	 * This method lets the baby eat, after making sure that he can 
	 * by checking on the pots 
	 * 
	 * @throws InterruptedException
	 */

	public void eat() throws InterruptedException {
		System.out.println(this.name + " is now hungry.");
		int freePot = checkForFood();
		if (freePot != -1) {

			System.out.println(this.name + " is now eating.");
			this.sleep(200);
			checkPots.down();
			pots.get(freePot).full = false;
			pots.get(freePot).isUsed = false;
			checkPots.up();
			eating.releaseAll();

		} else {

			if (checkIfUsed()) {

				eating.block();
				this.eat();

			} else
				wakeUpMother();
		}

	}
	
	/**
	 * This method lets me in a pot where it sets the flag of the isUsed in the pot 
	 * 
	 * 
	 * @return the number of the pot i am eating in -1 if non
	 * @throws InterruptedException
	 */

	public int checkForFood() throws InterruptedException {

		checkPots.down();
		int freePot = checkFreePot();

		if (freePot != -1)
			pots.get(freePot).isUsed = true;

		checkPots.up();
		return (freePot);

	}

	/**
	 * 
	 * @return the number of the free pot or -1 if non are free
	 */
	
	public int checkFreePot() {

		for (int i = 0; i < pots.size(); i++)
			if (!pots.get(i).isUsed && pots.get(i).full)
				return (i);
		return -1;

	}
	
	/**
	 * 
	 * @return true if any pot is used false if non
	 */
	public boolean checkIfUsed() {

		for (int i = 0; i < pots.size(); i++)
			if (pots.get(i).isUsed)
				return (true);

		return (false);

	}
	
	/**
	 * 
	 * This method handles waking up the mother and makes sure only one baby wakes the mother up
	 * 
	 * @throws InterruptedException
	 */

	public synchronized void wakeUpMother() throws InterruptedException {
		wakeUpMother.down();

		if (!mother.sleeping) {


			wakeUpMother.up();
			eating.block();


		} else {

			checkPots.down();
			if (checkFreePot() == -1) {

				checkPots.up();
				System.out.println("The pots are now empty.");
				System.out.println(this.name + " has just woken up our mother.");
				mother.sleepingMother.up();
				mother.sleeping = false;

				wakeUpMother.up();
				eating.block();


			} else {

				checkPots.up();

				wakeUpMother.up();

			}

		}

		eat();

	}
}
